#include "StdAfx.h"
#include "ZoarMachine.h"

CZoarMachine::CZoarMachine()
{
}

CZoarMachine::~CZoarMachine()
{
}

int CZoarMachine::Init()
{
CBurgerTimeMachine::Init();
MainCPU->SetUser(this);
SoundCPU->SetUser(this);
MainCPU->SetRead(ReadMainCPU);
MainCPU->SetWrite(WriteMainCPU);
MainCPU->SetOp(OpMainCPU);
return(0);
}

void CZoarMachine::Reset()
{
int n;

CBurgerTimeMachine::Reset();
for(n=0;n<64;n++)
	WritePalette(n,~PROM[n]);
memset(&MainROM[0xD50A],0xEA,8);		//mame does this to get it to work
memset(&NewROM[0xD50A],0xEA,8);		//mame does this to get it to work
}

void CZoarMachine::Poll()
{
/*u32 n;

Input->Poll();
n = Input->Get();
Input1 = Input2 = Input3 = 0;
if(n & I_UP)		Input1 |= 4;
if(n & I_DOWN)		Input1 |= 8;
if(n & I_LEFT)		Input1 |= 2;
if(n & I_RIGHT)	Input1 |= 1;
if(n & I_B1)		Input1 |= 0x10;
if(n & I_B2)		Input1 |= 0x20;
if(n & I_B3)		Input3 |= 0x04;
if(n & I_START1)	Input3 |= 0x01;
if(n & I_START2)	Input3 |= 0x02;
if(n & I_COIN1)	Input3 |= 0x40;
if(n & I_COIN2)	Input3 |= 0x80;
if(Input3 & 0xC0)
	MainCPU->NMI();
Input1 = ~Input1;
Input2 = ~Input2;
Input3 = ~Input3;
n = Input->GetDip();
Dip1 = (u8)n & 0x7F;
Dip2 = (u8)(n >> 8);*/
}

void CZoarMachine::SaveState(CState *s)
{
CBurgerTimeMachine::SaveState(s);
s->Write8(Scroll2);
s->Write(ScrollRAM,4);
}

void CZoarMachine::LoadState(CState *s)
{
CBurgerTimeMachine::LoadState(s);
Scroll2 = s->Read8();
s->Read(ScrollRAM,4);
}

void CZoarMachine::RenderScreen(u8 *dest,int pitch)
{
u8 pal;

pal = (VideoControl & 0x30) >> 1;
memset(dest,0,256*pitch);
if(Scroll & 4)
	{
	RenderBackground(dest,pitch,pal);
	RenderChars(dest,pitch,0,pal | 8);
	}
else
	RenderChars(dest,pitch,0,pal | 8);
//RenderSprites(dest,pitch,VideoRAM + 0x20);
RenderSprites(dest,pitch);
}

static u8 tmpscr[256*(256*3)];

void CZoarMachine::RenderBackground(u8 *dest,int pitch,int oor)
{
int i,start,x,y;
u8 *b[3];

b[0] = BGROM + 0x0000;
b[1] = BGROM + 0x0800;
b[2] = BGROM + 0x1000;
start = ScrollRAM[Scroll & 3] * 256;
//if(GetAsyncKeyState('1')) start = ScrollRAM[0 * 256];
//if(GetAsyncKeyState('2')) start = ScrollRAM[1 * 256];
//if(GetAsyncKeyState('3')) start = ScrollRAM[2 * 256];
//if(GetAsyncKeyState('4')) start = ScrollRAM[3 * 256];
if(Scroll2 == 0)
	{
	for(i=0;i<0x100;i++)
		{
		x = 240 - (16 * (i / 16) + 0);
		y = 16 * (i % 16);
		if(VideoControl & 0x80)
			{
			x = 240 - x;
			y = 240 - y;
			}
		drawtile_16x16_or_notrans(dest,pitch,VROM[start + i],(u8)x,(u8)y,b,oor);
		}
	}
else		//draw partial tile on left and right
	{
	u8 fineoffset = Scroll2 & 0xF;							//fine x offset
//	u8 offset = (Scroll2 + ((Scroll & 3) << 8)) / 16;	//x offset
	u8 offset = Scroll2 / 16;	//x offset
	int sx,sy;

	for(sy=0;sy<32;sy++)
		{
		for(sx=0;sx<16;sx++)
			{
			u8 tile;

			x = (496 - (16 * sy)) + Scroll2;
			y = sx * 16;
			if(x >= 256)				//switch current vram table
				{
				x -= 256;
				start = ScrollRAM[(Scroll + 1) & 3] * 256;
				if(sy == 0)message("switching vram bank %d -> %d (start = $%X)\n",Scroll&3,(Scroll+1)&3,start);
				}
			tile = VROM[start + (sx + (sy * 16))];
//			if(x < 256)
//				drawtile_16x16_or_notrans(dest,pitch,tile,(u8)x,(u8)y,b,or);
//			else
			if(x >= 256)
				{
				x -= 256;
				drawtile_16x16_or_notrans(dest,pitch,tile,(u8)x,(u8)y,b,oor);
				}
			}
		}
/*	for(i=0;i<0x100;i++)
		{
		x = 240 - (16 * (i / 16) + 0);
		y = 16 * (i % 16);
		if(VideoControl & 0x80)
			{
			x = 240 - x;
			y = 240 - y;
			}
		drawtile_16x16_or_notrans(dest,pitch,VROM[start + i],(u8)x,(u8)y,b,oor);
		}	*/
	}
}

u8 CZoarMachine::OpMainCPU(void *user,u32 addr)
{
CZoarMachine *M = (CZoarMachine*)user;

return(M->NewROM[addr]);
}

u8 CZoarMachine::ReadMainCPU(void *user,u32 addr)
{
CZoarMachine *M = (CZoarMachine*)user;

switch(addr & 0xF000)
	{
	case 0x0000:
		if(addr < 0x800)
			return(M->MainRAM[addr]);
		break;
	case 0x8000:
		if(addr < 0x8400)
			return(M->VideoRAM[addr & 0x3FF]);
		else if(addr < 0x8800)
			return(M->ColorRAM[addr & 0x3FF]);
		else if(addr < 0x8C00)
			{
			addr &= 0x3FF;
			return(M->VideoRAM[MirrorRAMAddr(addr)]);
			}
		addr &= 0x3FF;
		return(M->ColorRAM[MirrorRAMAddr(addr)]);
	case 0x9000:
		switch(addr)
			{
			case 0x9800:	return((M->Dip[0] & 0x7F) | M->VBlank);
			case 0x9801:	return(M->Dip[1]);
			case 0x9802:	return(M->InputData[0]);
			case 0x9803:	return(M->InputData[1]);
			case 0x9804:	return(M->InputData[2]);
			}
		break;
	case 0xD000:
	case 0xE000:
	case 0xF000:
		return(M->MainROM[addr]);
	}
message("unhandled read (main cpu, addr $%04X)\n",addr);
return(0);
}

void CZoarMachine::WriteMainCPU(void *user,u32 addr,u8 data)
{
CZoarMachine *M = (CZoarMachine*)user;

switch(addr & 0xF000)
	{
	case 0x0000:
		if(addr < 0x800)
			M->MainRAM[addr] = data;
		break;
	case 0x8000:
		if(addr < 0x8400)
			M->VideoRAM[addr & 0x3FF] = data;
		else if(addr < 0x8800)
			M->ColorRAM[addr & 0x3FF] = data;
		else if(addr < 0x8C00)
			{
			addr &= 0x3FF;
			M->VideoRAM[MirrorRAMAddr(addr)] = data;
			}
		else
			{
			addr &= 0x3FF;
			M->ColorRAM[MirrorRAMAddr(addr)] = data;
			}
		break;
	case 0x9000:
		switch(addr)
			{
			case 0x9000:
				M->VideoControl = data;
				break;
			case 0x9800:
			case 0x9801:
			case 0x9802:
			case 0x9803:
				M->ScrollRAM[addr & 3] = data;
				break;
			case 0x9804:
				M->Scroll2 = data;
				message("scroll2 reg write: $%02X\n",data);
				break;
			case 0x9805:
				M->Scroll = data;
				message("scroll reg write: $%02X\n",data);
				break;
			case 0x9806:
				M->WriteSoundControl(data);
				break;
			}
		break;
	default:
		message("unhandled write (main cpu, addr $%04X = $%02X)\n",addr,data);
		break;
	}
M->btimeDecrypt();
}
